Bayesian Blocks, provide an adaptive, data-driven method for optimal segmentation of time series or event data. Instead of relying on fixed bin sizes, Bayesian Blocks dynamically determine change points in the data, dividing it into piecewise constant segments (blocks) that best represent the structure of the signal. We follow the formalization of Scargle et al. (2013).
Key features of the Bayesian Blocks algorithm include:
Agilepy implements a AGBayesianBlocks class that works with:
The Bayesian Blocks algorithm has the following steps:
YAML configuration file for AGBayesianBlocks. You can do it manually or by using AGBayesianBlocks.getConfiguration().AGBayesianBlocks object, and load the data with AGBayesianBlocks.selectEvents().AGBayesianBlocks.bayesianBlocks().Note: the custom light curve format is a text file with three columns: bin start time, bin stop times, flux. Columns do not need an header and must be separated by white spaces.
# Import the relevant classes
import agilepy
from agilepy.api.AGBayesianBlocks import AGBayesianBlocks
Aperture Photometry Light Curves can be obtained with AGAnalysis.aperturePhotometry().
They are text files with no header and 4 columns separated by white spaces: bin start time, bin stop time, on-source exposure, on-source counts.
# Prepare the Configuration File.
# You can create it manually or use AGBayesianBlocks.getConfiguration
outputDir_ap = "/home/flareadvocate/workspace/shared_dir/"
confFilePath_ap = "/home/flareadvocate/workspace/shared_dir/tutorial_bb_ap.yaml"
AGBayesianBlocks.getConfiguration(confFilePath=confFilePath_ap,
outputDir=outputDir_ap,
userName="my-name",
sourceName="bb-source",
verboselvl=0,
filePath="$AGILE/agilepy-test-data/bayesian_blocks/3C454.3_2010flare_86400s.ap",
fileMode="AGILE_AP",
tstart="null",
tstop="null",
rateCorrection=0,
fitness="events",
gamma=0.35,
p0="null",
useerror="true"
)
The YAML file has the following sections and field:
output: common to all agilepy classes, sets the output fieldsselection: include arguments used by AGBayesianBlocks.selectEvents() used to prepare the data:filePath: path to the input filefileMode: defines the input file format: AGILE_AP, AGILE_MLE, CUSTOM_LC (binned) or AGILE_PH (unbinned).tstart, tstop: start and stop times for data selection within the input file. For AGILE_AP and AGILE_MLE must be in MJD format, for CUSTOM_LC, AGILE_PH in the same time format of the times provided.ratecorrection: the Bayesian Blocks algorithm works with integers, so fluxes need a correction factor for a correct statistical treatment. If 0 (default), the correction factor is the mean exposure. If a float is provided it will be applied as a correction factor for the flux. If -1, the algorithm will work with counts instead of fluxes.bayesianblocks: arguments used by AGBayesianBlocks.bayesianBlocks() to compute the blocks:fitness: set the type of algorithm. Possible values are events (binned light curve or unbinned event data), measures (sequence of flux measurements with Gaussian errors), regular_events(0/1 data measured regularly).useerror: boolean to include errors in the computation of the blocks.gamma, p0: arguments on the prior. p0, suggested for unbinned data, gives the false alarm probability to compute the prior. gamma, suggested for binned data, gives the slope of the prior on the number of bins.# Create the AGBayesianBlocks object
ag_bb_ap = AGBayesianBlocks(confFilePath_ap)
Log level set to WARNING and output to /home/flareadvocate/workspace/shared_dir/my-name_bb-source_20251005-142631/logs
# You can Use the setOptions() method to change the configuration, e.g.:
ag_bb_ap.setOptions(gamma=0.35)
# Check configuration.
ag_bb_ap.printOptions()
{ 'bayesianblocks': { 'fitness': 'events',
'gamma': 0.35,
'p0': None,
'useerror': True},
'output': { 'filenameprefix': 'analysis_product',
'outdir': PosixPath('/home/flareadvocate/workspace/shared_dir/my-name_bb-source_20251005-142631'),
'sourcename': 'bb-source',
'username': 'my-name',
'verboselvl': 0},
'selection': { 'file_mode': 'AGILE_AP',
'file_path': '/home/flareadvocate/agiletools/agilepy-test-data/bayesian_blocks/3C454.3_2010flare_86400s.ap',
'ratecorrection': 0,
'tstart': None,
'tstop': None}}
# Select Events
# If no argument is provided, they are read from the configuration file.
ag_bb_ap.selectEvents()
Select Events. FileMode=AGILE_AP, DataMode=BINNED Read input file /home/flareadvocate/agiletools/agilepy-test-data/bayesian_blocks/3C454.3_2010flare_86400s.ap Time Range selected (MJD): 55497.0-55562.0 Total number of rows selected (no zero-exposure): 65 Total number of counts selected (no zero-exposure): 1889 Apply Bayesian Blocks on AP FLUX (= CTS/EXP) scaled to integers with a mean exposure factor=4.54e+06
# You can Inspect the selected data with getDataIn()
selected_events_ap = ag_bb_ap.getDataIn()
# Print
display(selected_events_ap)
# Plot the Data
ag_bb_ap.plotBayesianBlocks()
{'x': array([ 10, 15, 13, 10, 10, 18, 13, 16, 14, 19, 16, 21, 11,
14, 8, 13, 11, 17, 17, 22, 82, 107, 104, 102, 52, 26,
43, 32, 30, 36, 44, 43, 40, 35, 33, 30, 29, 25, 18,
18, 16, 23, 17, 21, 23, 26, 32, 28, 16, 32, 40, 26,
34, 46, 34, 29, 31, 25, 27, 12, 20, 15, 15, 15, 13]),
't': array([2.153520e+08, 2.154384e+08, 2.155248e+08, 2.156112e+08,
2.156976e+08, 2.157840e+08, 2.158704e+08, 2.159568e+08,
2.160432e+08, 2.161296e+08, 2.162160e+08, 2.163024e+08,
2.163888e+08, 2.164752e+08, 2.165616e+08, 2.166480e+08,
2.167344e+08, 2.168208e+08, 2.169072e+08, 2.169936e+08,
2.170800e+08, 2.171664e+08, 2.172528e+08, 2.173392e+08,
2.174256e+08, 2.175120e+08, 2.175984e+08, 2.176848e+08,
2.177712e+08, 2.178576e+08, 2.179440e+08, 2.180304e+08,
2.181168e+08, 2.182032e+08, 2.182896e+08, 2.183760e+08,
2.184624e+08, 2.185488e+08, 2.186352e+08, 2.187216e+08,
2.188080e+08, 2.188944e+08, 2.189808e+08, 2.190672e+08,
2.191536e+08, 2.192400e+08, 2.193264e+08, 2.194128e+08,
2.194992e+08, 2.195856e+08, 2.196720e+08, 2.197584e+08,
2.198448e+08, 2.199312e+08, 2.200176e+08, 2.201040e+08,
2.201904e+08, 2.202768e+08, 2.203632e+08, 2.204496e+08,
2.205360e+08, 2.206224e+08, 2.207088e+08, 2.207952e+08,
2.208816e+08]),
'sigma': array([ 3.16227766, 3.87298335, 3.60555128, 3.16227766, 3.16227766,
4.24264069, 3.60555128, 4. , 3.74165739, 4.35889894,
4. , 4.58257569, 3.31662479, 3.74165739, 2.82842712,
3.60555128, 3.31662479, 4.12310563, 4.12310563, 4.69041576,
9.05538514, 10.34408043, 10.19803903, 10.09950494, 7.21110255,
5.09901951, 6.55743852, 5.65685425, 5.47722558, 6. ,
6.63324958, 6.55743852, 6.32455532, 5.91607978, 5.74456265,
5.47722558, 5.38516481, 5. , 4.24264069, 4.24264069,
4. , 4.79583152, 4.12310563, 4.58257569, 4.79583152,
5.09901951, 5.65685425, 5.29150262, 4. , 5.65685425,
6.32455532, 5.09901951, 5.83095189, 6.78232998, 5.83095189,
5.38516481, 5.56776436, 5. , 5.19615242, 3.46410162,
4.47213595, 3.87298335, 3.87298335, 3.87298335, 3.60555128]),
'dt': 86400.0,
'datamode': 2,
't_delta': array([86400., 86400., 86400., 86400., 86400., 86400., 86400., 86400.,
86400., 86400., 86400., 86400., 86400., 86400., 86400., 86400.,
86400., 86400., 86400., 86400., 86400., 86400., 86400., 86400.,
86400., 86400., 86400., 86400., 86400., 86400., 86400., 86400.,
86400., 86400., 86400., 86400., 86400., 86400., 86400., 86400.,
86400., 86400., 86400., 86400., 86400., 86400., 86400., 86400.,
86400., 86400., 86400., 86400., 86400., 86400., 86400., 86400.,
86400., 86400., 86400., 86400., 86400., 86400., 86400., 86400.,
86400.]),
'cts': array([ 5, 9, 9, 7, 7, 13, 10, 13, 12, 16, 14, 19, 10,
13, 8, 13, 11, 17, 16, 22, 48, 110, 104, 96, 53, 17,
47, 33, 32, 27, 48, 49, 44, 38, 36, 33, 35, 30, 21,
21, 19, 28, 20, 25, 27, 30, 38, 36, 20, 38, 50, 31,
44, 49, 42, 35, 29, 29, 31, 15, 23, 15, 16, 17, 16]),
'exp': array([2101588.49, 2597493.05, 2979020.64, 3084947.99, 3148670.51,
3225841.22, 3401596.4 , 3526623.34, 3695355.99, 3799344.2 ,
3877861.81, 3926297.66, 4041705.14, 4034194.55, 4409486.21,
4475049.98, 4239884.88, 4304468.34, 4236756.37, 4399808.92,
2626440.97, 4631478.27, 4526426.58, 4256707.12, 4573918.01,
2888742.28, 4924013.38, 4633562.25, 4745339.52, 3350976.14,
4941008.25, 5093324.51, 4909419.86, 4808191.84, 4888839.72,
4951293.57, 5308416.34, 5327580.8 , 5069708.45, 5204493.75,
5320259.72, 5351863.22, 5100026.2 , 5228994.2 , 5198898.16,
5234436.05, 5391584.13, 5681692.15, 5498660.5 , 5301896.47,
5544937.71, 5215427.53, 5715002.58, 4812586.15, 5595445.37,
5430229.6 , 4226018.21, 5221943.42, 5160905.07, 5286271.63,
5198024.96, 4439673.36, 4555862.44, 4863760.09, 5404708.57]),
'data_cells': array([2.153088e+08, 2.153952e+08, 2.154816e+08, 2.155680e+08,
2.156544e+08, 2.157408e+08, 2.158272e+08, 2.159136e+08,
2.160000e+08, 2.160864e+08, 2.161728e+08, 2.162592e+08,
2.163456e+08, 2.164320e+08, 2.165184e+08, 2.166048e+08,
2.166912e+08, 2.167776e+08, 2.168640e+08, 2.169504e+08,
2.170368e+08, 2.171232e+08, 2.172096e+08, 2.172960e+08,
2.173824e+08, 2.174688e+08, 2.175552e+08, 2.176416e+08,
2.177280e+08, 2.178144e+08, 2.179008e+08, 2.179872e+08,
2.180736e+08, 2.181600e+08, 2.182464e+08, 2.183328e+08,
2.184192e+08, 2.185056e+08, 2.185920e+08, 2.186784e+08,
2.187648e+08, 2.188512e+08, 2.189376e+08, 2.190240e+08,
2.191104e+08, 2.191968e+08, 2.192832e+08, 2.193696e+08,
2.194560e+08, 2.195424e+08, 2.196288e+08, 2.197152e+08,
2.198016e+08, 2.198880e+08, 2.199744e+08, 2.200608e+08,
2.201472e+08, 2.202336e+08, 2.203200e+08, 2.204064e+08,
2.204928e+08, 2.205792e+08, 2.206656e+08, 2.207520e+08,
2.208384e+08, 2.209248e+08]),
'rate': array([2.37915273e-06, 3.46487934e-06, 3.02112710e-06, 2.26908201e-06,
2.22316053e-06, 4.02995656e-06, 2.93979615e-06, 3.68624567e-06,
3.24731908e-06, 4.21125309e-06, 3.61023695e-06, 4.83916444e-06,
2.47420325e-06, 3.22245242e-06, 1.81427033e-06, 2.90499549e-06,
2.59441006e-06, 3.94938437e-06, 3.77647393e-06, 5.00021715e-06,
1.82756820e-05, 2.37505163e-05, 2.29761818e-05, 2.25526439e-05,
1.15874399e-05, 5.88491404e-06, 9.54505936e-06, 7.12195029e-06,
6.74345847e-06, 8.05735370e-06, 9.71461644e-06, 9.62043551e-06,
8.96236241e-06, 7.90317884e-06, 7.36371042e-06, 6.66492494e-06,
6.59330349e-06, 5.63107368e-06, 4.14225003e-06, 4.03497458e-06,
3.57125422e-06, 5.23182280e-06, 3.92154848e-06, 4.78103418e-06,
5.19340814e-06, 5.73127644e-06, 7.04802134e-06, 6.33614055e-06,
3.63724947e-06, 7.16724670e-06, 9.01723385e-06, 5.94390389e-06,
7.69903414e-06, 1.01816359e-05, 7.50610492e-06, 6.44539966e-06,
6.86225155e-06, 5.55348798e-06, 6.00669836e-06, 2.83753864e-06,
4.42475751e-06, 3.37862694e-06, 3.51195854e-06, 3.49523819e-06,
2.96038164e-06])}
2025-10-05 14:26:31 | WARNING | agilepy.api.AGBayesianBlocks.AGBayesianBlocks | Bayesian Blocks not computed yet. Plotting only data... | (AGBayesianBlocks.py:254)
# Compute Bayesian Blocks
ag_bb_ap.bayesianBlocks()
/home/flareadvocate/Agilepy/agilepy/external_packages/BBrta/python_code/bayesian_blocks.py:756: RuntimeWarning: divide by zero encountered in scalar divide
# You can Inspect the results with getDataout()
blocks_computed_ap = ag_bb_ap.getDataOut()
# Print
display(blocks_computed_ap.keys())
display(len(blocks_computed_ap['data_cells']))
display(len(blocks_computed_ap['blockrate']))
display(blocks_computed_ap['N_change_points'])
display(blocks_computed_ap)
dict_keys(['data_cells', 'ncp_prior', 'N', 'change_points', 'edge_points', 'N_data_cells', 'N_change_points', 'edge_vec', 'sum_blocks', 'mean_blocks', 'dt_event_vec', 'dt_block_vec', 'blockrate', 'blockrate2', 'eventrate'])
66
17
16
{'data_cells': array([2.153088e+08, 2.153952e+08, 2.154816e+08, 2.155680e+08,
2.156544e+08, 2.157408e+08, 2.158272e+08, 2.159136e+08,
2.160000e+08, 2.160864e+08, 2.161728e+08, 2.162592e+08,
2.163456e+08, 2.164320e+08, 2.165184e+08, 2.166048e+08,
2.166912e+08, 2.167776e+08, 2.168640e+08, 2.169504e+08,
2.170368e+08, 2.171232e+08, 2.172096e+08, 2.172960e+08,
2.173824e+08, 2.174688e+08, 2.175552e+08, 2.176416e+08,
2.177280e+08, 2.178144e+08, 2.179008e+08, 2.179872e+08,
2.180736e+08, 2.181600e+08, 2.182464e+08, 2.183328e+08,
2.184192e+08, 2.185056e+08, 2.185920e+08, 2.186784e+08,
2.187648e+08, 2.188512e+08, 2.189376e+08, 2.190240e+08,
2.191104e+08, 2.191968e+08, 2.192832e+08, 2.193696e+08,
2.194560e+08, 2.195424e+08, 2.196288e+08, 2.197152e+08,
2.198016e+08, 2.198880e+08, 2.199744e+08, 2.200608e+08,
2.201472e+08, 2.202336e+08, 2.203200e+08, 2.204064e+08,
2.204928e+08, 2.205792e+08, 2.206656e+08, 2.207520e+08,
2.208384e+08, 2.209248e+08]),
'ncp_prior': 1.0498221244986778,
'N': 65,
'change_points': [5,
12,
17,
20,
21,
24,
25,
26,
35,
38,
45,
48,
49,
53,
54,
59],
'edge_points': array([2.157408e+08, 2.163456e+08, 2.167776e+08, 2.170368e+08,
2.171232e+08, 2.173824e+08, 2.174688e+08, 2.175552e+08,
2.183328e+08, 2.185920e+08, 2.191968e+08, 2.194560e+08,
2.195424e+08, 2.198880e+08, 2.199744e+08, 2.204064e+08]),
'N_data_cells': 65,
'N_change_points': 16,
'edge_vec': array([2.204064e+08, 2.204928e+08, 2.205792e+08, 2.206656e+08,
2.207520e+08, 2.208384e+08, 2.209248e+08]),
'sum_blocks': array([ 58., 117., 57., 56., 82., 313., 52., 26., 336., 84., 136.,
86., 16., 132., 46., 146., 90.]),
'mean_blocks': array([ 11.6 , 16.71428571, 11.4 , 18.66666667,
82. , 104.33333333, 52. , 26. ,
37.33333333, 28. , 19.42857143, 28.66666667,
16. , 33. , 46. , 29.2 ,
15. ]),
'dt_event_vec': array([345600., 518400., 345600., 172800., 0., 172800., 0.,
0., 691200., 172800., 518400., 172800., 0., 259200.,
0., 345600., 432000.]),
'dt_block_vec': array([432000., 604800., 432000., 259200., 86400., 259200., 86400.,
86400., 777600., 259200., 604800., 259200., 86400., 345600.,
86400., 432000., 518400.]),
'blockrate': array([0.00013426, 0.00019345, 0.00013194, 0.00021605, 0.00094907,
0.00120756, 0.00060185, 0.00030093, 0.0004321 , 0.00032407,
0.00022487, 0.00033179, 0.00018519, 0.00038194, 0.00053241,
0.00033796, 0.00017361]),
'blockrate2': array([2.67148034e-06, 3.79485313e-06, 2.60206631e-06, 4.24202515e-06,
1.82756820e-05, 2.30931140e-05, 1.15874399e-05, 5.88491404e-06,
8.33690283e-06, 6.29643404e-06, 4.41089892e-06, 6.37181277e-06,
3.63724947e-06, 7.45685465e-06, 1.01816359e-05, 6.47478849e-06,
3.43475024e-06]),
'eventrate': array([0.00016782, 0.00022569, 0.00016493, 0.00032407, inf,
0.00181134, inf, inf, 0.00048611, 0.00048611,
0.00026235, 0.00049769, inf, 0.00050926, inf,
0.00042245, 0.00020833])}
# Plot
ag_bb_ap.plotBayesianBlocks(saveImage=False, plotRate=True, plotDataCells=True)
Maximum Likelihood Light Curves can be obtained with AGAnalysis.lightCurve().
They are text files with header and multiple columns separated by white spaces.
# Prepare the Configuration File.
# You can create it manually or use AGBayesianBlocks.getConfiguration
outputDir_mle = "/home/flareadvocate/workspace/shared_dir/"
confFilePath_mle = "/home/flareadvocate/workspace/shared_dir/tutorial_bb_mle.yaml"
AGBayesianBlocks.getConfiguration(confFilePath=confFilePath_mle,
outputDir=outputDir_mle,
userName="my-name",
sourceName="bb-source",
verboselvl=0,
filePath="$AGILE/agilepy-test-data/bayesian_blocks/3C454.3_2010flare_86400s_lc_mle.txt",
fileMode="AGILE_MLE",
tstart="null",
tstop="null",
rateCorrection=0,
fitness="events",
gamma=0.35,
p0="null",
useerror="true"
)
# Create the AGBayesianBlocks object
ag_bb_mle = AGBayesianBlocks(confFilePath_mle)
# You can Use the setOptions() method to change the configuration, e.g.:
# ag_bb_mle.setOptions(gamma=0.35)
# Check configuration.
ag_bb_mle.printOptions()
Log level set to WARNING and output to /home/flareadvocate/workspace/shared_dir/my-name_bb-source_20251005-142636/logs
{ 'bayesianblocks': { 'fitness': 'events',
'gamma': 0.35,
'p0': None,
'useerror': True},
'output': { 'filenameprefix': 'analysis_product',
'outdir': PosixPath('/home/flareadvocate/workspace/shared_dir/my-name_bb-source_20251005-142636'),
'sourcename': 'bb-source',
'username': 'my-name',
'verboselvl': 0},
'selection': { 'file_mode': 'AGILE_MLE',
'file_path': '/home/flareadvocate/agiletools/agilepy-test-data/bayesian_blocks/3C454.3_2010flare_86400s_lc_mle.txt',
'ratecorrection': 0,
'tstart': None,
'tstop': None}}
# Select Events
ag_bb_mle.selectEvents()
# Inspect
selected_events_mle = ag_bb_mle.getDataIn()
Select Events. FileMode=AGILE_MLE, DataMode=BINNED Read input file /home/flareadvocate/agiletools/agilepy-test-data/bayesian_blocks/3C454.3_2010flare_86400s_lc_mle.txt Time Range selected (MJD): 55510.0-55530.0 Total number of rows selected (no zero-exposure, 3sigma): 20 Total number of source photons selected (no zero-exposure, sqrt(ts)>3): 1208.8043 Apply Bayesian Blocks on MLE FLUX scaled to integers with a mean exposure factor=3.54e+06
# Compute Bayesian Blocks
ag_bb_mle.bayesianBlocks()
# Inspect
blocks_computed_mle = ag_bb_mle.getDataOut()
/home/flareadvocate/Agilepy/agilepy/external_packages/BBrta/python_code/bayesian_blocks.py:756: RuntimeWarning: divide by zero encountered in scalar divide
# Print
display(blocks_computed_mle['N_change_points'])
# Plot
ag_bb_mle.plotBayesianBlocks(saveImage=False, plotRate=True, plotDataCells=True)
8
Photon list files are text files separated by whitespaces where the first column is the photon arrival times. Please perform any other selection (e.g. position, energy, data quality) beforehand.
# Prepare the Configuration File.
# You can create it manually or use AGBayesianBlocks.getConfiguration
outputDir_ph = "/home/flareadvocate/workspace/shared_dir/"
confFilePath_ph = "/home/flareadvocate/workspace/shared_dir/tutorial_bb_ph.yaml"
filePath_ph = agilepy.__path__[0]+"/testing/unittesting/api/data/test_data.ph"
AGBayesianBlocks.getConfiguration(confFilePath=confFilePath_ph,
outputDir=outputDir_ph,
userName="my-name",
sourceName="bb-source",
verboselvl=0,
filePath=filePath_ph,
fileMode="AGILE_PH",
tstart="null",
tstop="null",
rateCorrection=0,
fitness="events",
gamma="null",
p0=0.5,
useerror="true"
)
# Create the AGBayesianBlocks object
ag_bb_ph = AGBayesianBlocks(confFilePath_ph)
# Check configuration.
ag_bb_ph.printOptions()
Log level set to WARNING and output to /home/flareadvocate/workspace/shared_dir/my-name_bb-source_20251005-142637/logs
{ 'bayesianblocks': { 'fitness': 'events',
'gamma': None,
'p0': 0.5,
'useerror': True},
'output': { 'filenameprefix': 'analysis_product',
'outdir': PosixPath('/home/flareadvocate/workspace/shared_dir/my-name_bb-source_20251005-142637'),
'sourcename': 'bb-source',
'username': 'my-name',
'verboselvl': 0},
'selection': { 'file_mode': 'AGILE_PH',
'file_path': '/home/flareadvocate/Agilepy/agilepy/testing/unittesting/api/data/test_data.ph',
'ratecorrection': 0,
'tstart': None,
'tstop': None}}
# Select Events
ag_bb_ph.selectEvents()
# Inspect
selected_events_ph = ag_bb_ph.getDataIn()
Select Events. FileMode=AGILE_PH, DataMode=UNBINNED Read input file /home/flareadvocate/Agilepy/agilepy/testing/unittesting/api/data/test_data.ph Number of photons selected: 1285
# Compute Bayesian Blocks
ag_bb_ph.bayesianBlocks()
# Inspect
blocks_computed_ph = ag_bb_ph.getDataOut()
# Print
display(blocks_computed_ph['N_change_points'])
# Plot
ag_bb_ph.plotBayesianBlocks(saveImage=False, plotRate=True)
2